﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Globalization;
using System.Linq;
using EstateNuke.Data.Properties;

namespace EstateNuke.Data
{
    /// <summary>
    /// </summary>
    public partial class LeaseAgreement
    {
        #region Fileds & Properties

        /// <summary>
        /// </summary>
        public string DisplayName
        {
            get
            {
                return string.Format("{0}{1}", SerialNumber, IsDeleted ? " (已删除)" : "");
            }
        }

        /// <summary>
        /// </summary>
        public Building Building
        {
            get
            {
                if (!PropertyReference.IsLoaded)
                {
                    PropertyReference.Load(MergeOption.PreserveChanges);
                }
                if (!Property.EntranceReference.IsLoaded)
                {
                    Property.EntranceReference.Load(MergeOption.PreserveChanges);
                }
                if (!Property.Entrance.BuildingReference.IsLoaded)
                {
                    Property.Entrance.BuildingReference.Load(MergeOption.PreserveChanges);
                }
                return Property.Entrance.Building;
            }
        }

        /// <summary>
        /// </summary>
        public Project Project
        {
            get
            {
                if (!PropertyReference.IsLoaded)
                {
                    PropertyReference.Load(MergeOption.PreserveChanges);
                }
                if (!Property.EntranceReference.IsLoaded)
                {
                    Property.EntranceReference.Load(MergeOption.PreserveChanges);
                }
                if (!Property.Entrance.BuildingReference.IsLoaded)
                {
                    Property.Entrance.BuildingReference.Load(MergeOption.PreserveChanges);
                }
                if (!Property.Entrance.Building.ProjectReference.IsLoaded)
                {
                    Property.Entrance.Building.ProjectReference.Load(MergeOption.PreserveChanges);
                }
                return Property.Entrance.Building.Project;
            }
        }

        /// <summary>
        /// </summary>
        internal IList<LeaseOrder> LeaseOrders
        {
            get
            {
                return InternalLeaseOrders.Where(leaseOrder => leaseOrder.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public LeaseOrder LeaseOrder
        {
            get
            {
                return InternalLeaseOrders.FirstOrDefault(leaseOrder => leaseOrder.IsDeleted == false);
            }
        }

        /// <summary>
        /// </summary>
        internal IList<LeaseContract> LeaseContracts
        {
            get
            {
                return InternalLeaseContracts.Where(leaseContract => leaseContract.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public LeaseContract LeaseContract
        {
            get
            {
                return InternalLeaseContracts.FirstOrDefault(leaseContract => leaseContract.IsDeleted == false);
            }
        }

        /// <summary>
        /// </summary>
        internal IList<LeaseCancellation> LeaseCancellations
        {
            get
            {
                return InternalLeaseCancellations.Where(leaseCancellation => leaseCancellation.IsDeleted == false).ToList();
            }
        }

        /// <summary>
        /// </summary>
        public LeaseCancellation LeaseCancellation
        {
            get
            {
                return InternalLeaseCancellations.FirstOrDefault(leaseCancellation => leaseCancellation.IsDeleted == false);
            }
        }

        #endregion

        #region Set LeaseAgreementState

        /// <summary>
        /// </summary>
        public void SetLeaseAgreementStateNone(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            LeaseAgreementStateId = 0;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            if (!PropertyReference.IsLoaded)
            {
                PropertyReference.Load(MergeOption.PreserveChanges);
            }
            if (!Property.ActiveLeaseAgreementReference.IsLoaded)
            {
                Property.ActiveLeaseAgreementReference.Load(MergeOption.PreserveChanges);
            }
            if (Property.ActiveLeaseAgreement == this && (Property.PropertyStateId == 1 || Property.PropertyStateId == 3 || Property.PropertyStateId == 4))
            {
                Property.SetPropertyStateLeasable(modifiedUser);
                Property.ActiveLeaseAgreement = null;
            }
        }

        /// <summary>
        /// </summary>
        public void SetLeaseAgreementStateOrdered(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            LeaseAgreementStateId = 1;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            if (!PropertyReference.IsLoaded)
            {
                PropertyReference.Load(MergeOption.PreserveChanges);
            }
            if (!Property.ActiveLeaseAgreementReference.IsLoaded)
            {
                Property.ActiveLeaseAgreementReference.Load(MergeOption.PreserveChanges);
            }
            if (Property.ActiveLeaseAgreement == this && (Property.PropertyStateId == 1 || Property.PropertyStateId == 3 || Property.PropertyStateId == 4))
            {
                Property.SetPropertyStateOrdered(modifiedUser);
            }
        }

        /// <summary>
        /// </summary>
        public void SetLeaseAgreementStateContracted(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            LeaseAgreementStateId = 2;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            if (!PropertyReference.IsLoaded)
            {
                PropertyReference.Load(MergeOption.PreserveChanges);
            }
            if (!Property.ActiveLeaseAgreementReference.IsLoaded)
            {
                Property.ActiveLeaseAgreementReference.Load(MergeOption.PreserveChanges);
            }
            if (Property.ActiveLeaseAgreement == this && (Property.PropertyStateId == 1 || Property.PropertyStateId == 3 || Property.PropertyStateId == 4))
            {
                Property.SetPropertyStateContracted(modifiedUser);
            }
            var leaseOrder = LeaseOrder;
            if (leaseOrder != null)
            {
                (leaseOrder.InternalLeaseOrderEngagedContractAlerts.ToList()).ForEach(leaseOrderEngagedContractAlert => leaseOrderEngagedContractAlert.Delete(modifiedUser));
            }
        }

        /// <summary>
        /// </summary>
        public void SetLeaseAgreementStateCancelled(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            LeaseAgreementStateId = 4;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            if (!PropertyReference.IsLoaded)
            {
                PropertyReference.Load(MergeOption.PreserveChanges);
            }
            if (!Property.ActiveLeaseAgreementReference.IsLoaded)
            {
                Property.ActiveLeaseAgreementReference.Load(MergeOption.PreserveChanges);
            }
            if (Property.ActiveLeaseAgreement == this && (Property.PropertyStateId == 1 || Property.PropertyStateId == 3 || Property.PropertyStateId == 4))
            {
                Property.SetPropertyStateLeasable(modifiedUser);
                Property.ActiveLeaseAgreement = null;
            }
            var leaseOrder = LeaseOrder;
            if (leaseOrder != null)
            {
                (leaseOrder.InternalLeaseOrderEngagedContractAlerts.ToList()).ForEach(leaseOrderEngagedContractAlert => leaseOrderEngagedContractAlert.Delete(modifiedUser));
            }
            var leaseContract = LeaseContract;
            if (leaseContract != null)
            {
                (leaseContract.InternalLeaseContractReceipts.SelectMany(leaseContractReceipt => leaseContractReceipt.InternalLeaseContractReceiptScheduledAlerts).ToList()).ForEach(leaseContractReceiptScheduledAlert => leaseContractReceiptScheduledAlert.Delete(modifiedUser));
            }
        }

        /// <summary>
        /// </summary>
        private void AutoSetLeaseAgreementState(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (LeaseCancellation != null)
            {
                SetLeaseAgreementStateCancelled(modifiedUser);
            }
            else if (LeaseContract != null)
            {
                SetLeaseAgreementStateContracted(modifiedUser);
            }
            else if (LeaseOrder != null)
            {
                SetLeaseAgreementStateOrdered(modifiedUser);
            }
            else
            {
                SetLeaseAgreementStateNone(modifiedUser);
            }
        }

        #endregion

        #region Create & Delete LeaseOrder

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public LeaseOrder CreateLeaseOrder(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (LeaseContract != null || LeaseCancellation != null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.CannotCreateSmallOrder, "已存在已租或取消协议"));
            }
            SetLeaseAgreementStateOrdered(modifiedUser);
            var leaseOrder = InternalLeaseOrders.FirstOrDefault(item => item.IsDeleted == false);
            if (leaseOrder != null)
            {
                return leaseOrder;
            }
            leaseOrder = InternalLeaseOrders.FirstOrDefault(item => item.IsDeleted);
            if (leaseOrder == null)
            {
                leaseOrder = new LeaseOrder
                                 {
                                     RowId = Guid.NewGuid(),
                                     CreatedDate = DateTime.Now,
                                 };
                InternalLeaseOrders.Add(leaseOrder);
            }
            leaseOrder.IsDeleted = false;
            leaseOrder.ModifiedDate = DateTime.Now;
            leaseOrder.ModifiedByUser = modifiedUser;
            leaseOrder.OrderNumber = string.Format("YX{0}{1}{2}", Project.CreatedDate.Year, Project.Code, (Project.AllLeaseOrdersCount + 1).ToString("00000"));
            leaseOrder.LeaseMonths = 12;
            leaseOrder.LeasePaymentTypeId = 1;
            leaseOrder.TotalAmount = Property.TotalPricePerMonth * 4;
            leaseOrder.DepositAmount = 1000;
            leaseOrder.LeaseAmount = Property.TotalPricePerMonth * 3;
            leaseOrder.GuarantyAmount = Property.TotalPricePerMonth;
            leaseOrder.OtherAmount = 0;
            leaseOrder.EngagedContractDate = DateTime.Now.Date.AddDays(7);
            leaseOrder.SignatureDate = DateTime.Now.Date;
            return leaseOrder;
        }

        /// <summary>
        /// </summary>
        /// <param name = "modifiedUser"></param>
        public void DeleteLeaseOrder(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var leaseOrder = LeaseOrder;
            if (leaseOrder != null)
            {
                leaseOrder.Delete(modifiedUser);
                AutoSetLeaseAgreementState(modifiedUser);
            }
        }

        #endregion

        #region Create & Delete LeaseContract

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public LeaseContract CreateLeaseContract(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            if (LeaseCancellation != null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.CannotCreateSmallOrder, "已存在取消协议"));
            }
            SetLeaseAgreementStateContracted(modifiedUser);
            var leaseContract = InternalLeaseContracts.FirstOrDefault(item => item.IsDeleted == false);
            if (leaseContract != null)
            {
                return leaseContract;
            }
            leaseContract = InternalLeaseContracts.FirstOrDefault(item => item.IsDeleted);
            if (leaseContract == null)
            {
                leaseContract = new LeaseContract
                                    {
                                        RowId = Guid.NewGuid(),
                                        CreatedDate = DateTime.Now,
                                    };
                InternalLeaseContracts.Add(leaseContract);
            }
            leaseContract.IsDeleted = false;
            leaseContract.ModifiedDate = DateTime.Now;
            leaseContract.ModifiedByUser = modifiedUser;
            var leaseOrder = LeaseOrder;
            leaseContract.ContractNumber = string.Format("CZ{0}{1}{2}", Project.CreatedDate.Year, Project.Code, (Project.AllLeaseContractsCount + 1).ToString("00000"));
            leaseContract.LeaseMonths = leaseOrder != null ? leaseOrder.LeaseMonths : (short) 12;
            leaseContract.BeginDate = DateTime.Now.Date;
            leaseContract.EndDate = leaseOrder != null ? DateTime.Now.Date.AddMonths(leaseOrder.LeaseMonths) : DateTime.Now.Date.AddMonths(12);
            leaseContract.LeasePaymentTypeId = leaseOrder != null ? leaseOrder.LeasePaymentTypeId : 1;
            leaseContract.TotalAmount = leaseOrder != null ? leaseOrder.TotalAmount : Property.TotalPricePerMonth * 4;
            leaseContract.LeaseAmount = leaseOrder != null ? leaseOrder.LeaseAmount : Property.TotalPricePerMonth * 3;
            leaseContract.GuarantyAmount = leaseOrder != null ? leaseOrder.GuarantyAmount : Property.TotalPricePerMonth;
            leaseContract.OtherAmount = leaseOrder != null ? leaseOrder.OtherAmount : 0;
            leaseContract.SignatureDate = DateTime.Now.Date;
            return leaseContract;
        }

        /// <summary>
        /// </summary>
        /// <param name = "modifiedUser"></param>
        public void DeleteLeaseContract(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var leaseContract = LeaseContract;
            if (leaseContract != null)
            {
                leaseContract.Delete(modifiedUser);
                AutoSetLeaseAgreementState(modifiedUser);
            }
        }

        #endregion

        #region Create & Delete LeaseCancellation

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public LeaseCancellation CreateLeaseCancellation(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            SetLeaseAgreementStateCancelled(modifiedUser);
            var leaseCancellation = InternalLeaseCancellations.FirstOrDefault(item => item.IsDeleted == false);
            if (leaseCancellation != null)
            {
                return leaseCancellation;
            }
            leaseCancellation = InternalLeaseCancellations.FirstOrDefault(item => item.IsDeleted);
            if (leaseCancellation == null)
            {
                leaseCancellation = new LeaseCancellation
                                        {
                                            RowId = Guid.NewGuid(),
                                            CreatedDate = DateTime.Now,
                                        };
                InternalLeaseCancellations.Add(leaseCancellation);
            }
            leaseCancellation.IsDeleted = false;
            leaseCancellation.ModifiedDate = DateTime.Now;
            leaseCancellation.ModifiedByUser = modifiedUser;
            leaseCancellation.DeductibleAmount = 0;
            leaseCancellation.CancellationDate = DateTime.Now;
            return leaseCancellation;
        }

        /// <summary>
        /// </summary>
        /// <param name = "modifiedUser"></param>
        public void DeleteLeaseCancellation(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            var leaseCancellation = LeaseCancellation;
            if (leaseCancellation != null)
            {
                leaseCancellation.Delete(modifiedUser);
                AutoSetLeaseAgreementState(modifiedUser);
            }
        }

        #endregion

        #region Ensure

        /// <summary>
        /// </summary>
        public void Ensure()
        {
            if (string.IsNullOrEmpty(SerialNumber))
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture, Resources.NotNullAllowed, RowId, "LeaseAgreement", "SerialNumber"));
            }
            SerialNumber = SerialNumber.Length > 32 ? SerialNumber.Substring(0, 32) : SerialNumber;
        }

        #endregion

        #region Delete

        /// <summary>
        /// </summary>
        public void Delete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = true;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
            ((List<LeaseOrder>) LeaseOrders).ForEach(leaseOrder => leaseOrder.Delete(modifiedUser));
            ((List<LeaseContract>) LeaseContracts).ForEach(leaseContract => leaseContract.Delete(modifiedUser));
            ((List<LeaseCancellation>) LeaseCancellations).ForEach(leaseCancellation => leaseCancellation.Delete(modifiedUser));
        }

        /// <summary>
        /// </summary>
        public void CancelDelete(User modifiedUser)
        {
            if (modifiedUser == null)
            {
                throw new ArgumentNullException("modifiedUser");
            }
            IsDeleted = false;
            ModifiedDate = DateTime.Now;
            ModifiedByUser = modifiedUser;
        }

        #endregion
    }
}